#pragma once
#include "stdafx.h"
#include "FbxObject.h"
#include "FbxTime.h"
#include "KFbxIO/kfbxiosettings.h"
#include "FbxPropertyDef.h"

namespace Skill
{
	namespace FbxSDK
	{
		ref class FbxTime;
		ref class FbxClassId;
		ref class FbxSdkManager;
		ref class FbxProperty;
		ref class FbxDataType;
		ref class FbxString;		
		namespace IO
		{
			// class to handle old StreamOptions information
			public ref class FbxSoInfo : IFbxNativePointer
			{
				BASIC_CLASS_DECLARE(FbxSoInfo,KsoInfo);
				INATIVEPOINTER_DECLARE(FbxSoInfo,KsoInfo);			
			public: 
				enum class ImpExp
				{
					Import = 0,
					Export
				};
			public: 
				DEFAULT_CONSTRUCTOR(FbxSoInfo,KsoInfo);				

				//! Set values to default 
				void Reset(ImpExp impExp);

				//! If pTimeMode is set to KTime::eDEFAULT_MODE, pCustomFrameRate is used instead.
				void SetTimeMode(FbxTime::TimeMode timeMode, double customFrameRate);

				//! A time mode set to KTime::eDEFAULT_MODE means a custom frame rate is set.
				property FbxTime::TimeMode TimeMode
				{
					FbxTime::TimeMode get();
				}

				//! Get frame period associated with time mode or a custom frame period if time mode is set to KTime::eDEFAULT_MODE.
				property FbxTime^ FramePeriod
				{
					FbxTime^ get();
				}
			protected:
				FbxObject^ ASF;
			public:

				void SetASFScene(FbxObject^ ASFScene, bool ASFSceneOwned);
				FbxObject^ GetASFScene();
			};

			public enum class FbxUILanguage
			{
				ENU = 0,			        // MAX 409 English - United States
				DEU,           	        // MAX 407 German - Germany
				FRA,            	        // MAX 40c French - France
				JPN,           	        // MAX 411 Japanese - Japan
				KOR,            	        // MAX 412 Korean(Extended Wansung) - Korea 
				CHS,	                    // MAX 804 Chinese - PRC
				UILanguageCount
			};

			// this class is located in the UserDataPtr of each KFbxIOSettings properties
			//public ref class PropInfo
			//{
			//internal:
			//	fbxsdk_200901::PropInfo*
			//public:
			//	PropInfo();
			//	~PropInfo();

			//	void            * UIWidget;            // UI widget for showing the property
			//	void            * cbValueChanged;      // call back when value changed
			//	void            * cbDirty;             // call back when value changed
			//	KStringList       labels;              // list of labels in many languages
			//};


			/** KFbxIOSettings
			*	Class used as container for IO settings.
			*   All settings are organised in a propertie hierarchie.
			*   A node of settings may contain a bunch of information related to an operation (ex: import / export)
			*   it may also contain informations related to a user dialog offering user options
			*/
			public ref class FbxIOSettings : FbxObject
			{
			internal:
				REF_DECLARE(FbxEmitter,KFbxIOSettings);
			public:				
				FbxIOSettings(KFbxIOSettings* instance) : FbxObject(instance)
				{
					_Free = false;
				}
			protected:
				static FbxIOSettings^ refIO;
				FbxSoInfo^ impInfo;			
				FbxSoInfo^ expInfo;

				virtual void CollectManagedMemory() override;
			public:				

				FBXOBJECT_DECLARE(FbxIOSettings);				

				//! Global allocator
				static void AllocateIOSettings(FbxSdkManager^ manager);

				static bool IsIOSettingsAllocated();

				//! Release memory
				void FreeIOSettings();

				//! Ref accessor
				static property FbxIOSettings^ IOSettingsRef
				{
					FbxIOSettings^ get();
				}

				//! Empty the settings hierarchies
				//virtual void Clear() override;

				//! Add a property group under the root prop
				FbxProperty^ AddPropertyGroup(String^ name, FbxDataType^ dataType, String^ label);
				FbxProperty^ AddPropertyGroup(String^ name);

				//! Add a property group under another parent prop
				FbxProperty^ AddPropertyGroup(	FbxProperty^ parentProperty, 
					String^ name,
					FbxDataType^ dataType, 
					String^ label,
					bool visible,
					bool savable,
					bool enabled);
				FbxProperty^ AddPropertyGroup(	FbxProperty^ parentProperty, 
					String^ name);

				//! Add a property under another parent prop with a value to set
				/*FbxProperty^ AddProperty(FbxProperty^ parentProperty, 
				String^ name, 
				FbxDataType^ dataType , 
				String^ label,
				void const*            pValue          = NULL,
				EFbxType               pValueType      = eUNIDENTIFIED,
				bool					pVisible		= true,
				bool					pSavable		= true,
				bool					pEnabled		= true
				);*/

				//! Add a property under another parent prop with a value to set and a min max values
				/*public: KFbxProperty AddPropertyMinMax(    KFbxProperty const     &pParentProperty, 
				char const*            pName, 
				KFbxDataType const     &pDataType      = KFbxDataType(), 
				char const*            pLabel          = "",
				void const*            pValue          = NULL,
				double const*			pMinValue		= NULL,
				double const*			pMaxValue		= NULL,
				EFbxType               pValueType      = eUNIDENTIFIED,									 
				bool					pVisible		= true,
				bool					pSavable		= true,
				bool					pEnabled		= true
				);*/


				//! get a prop by description ex: "Export|Animation|Bake"
				FbxProperty^ GetProperty(String^ name);

				//! get prop by description from a parent property
				FbxProperty^ GetProperty(FbxProperty^ parentProperty,String^ name);

				//! get/set a bool prop by prop path
				bool GetBoolProp(String^ name, bool defValue);
				void SetBoolProp(String^ name, bool value);

				//! get/set a double prop by prop path
				double GetDoubleProp(String^ name, double defValue);
				void   SetDoubleProp(String^ name, double value);

				//! get/set a int prop by prop path
				int    GetIntProp(String^ name, int defValue);
				void   SetIntProp(String^ name, int value);

				//! get/set a KTime prop by prop path
				FbxTime^  GetFbxTimeProp(String^ name, FbxTime^ defValue);
				void   SetFbxTimeProp(String^ name, FbxTime^ value);

				//! get/set an enum prop by prop path
				FbxString^ GetEnumProp(String^ name, FbxString^ defValue);
				int     GetEnumProp(String^ name, int defValue);
				int     GetEnumIndex(String^ name, FbxString^ value);

				void SetEnumProp(String^ name, FbxString^ value);
				void SetEnumProp(String^ name, int value);

				void RemoveEnumPropValue(String^ name, FbxString^ value);
				void EmptyEnumProp(String^ name);

				// set a specific flag value on a specific property
				bool SetFlag(String^ name, Skill::FbxSDK::FbxPropertyFlags::FbxPropertyFlagsType propFlag, bool value);

				//! get/set a string prop by prop path
				FbxString^ GetStringProp(String^ name, FbxString^ defValue);
				void SetStringProp(String^ name, FbxString^ value);


				//! Load the settings hierarchie from an XML file
				virtual bool ReadXMLFile(String^ path);

				//! Write the settings hierarchie to an XML file
				virtual bool WriteXMLFile(String^ path);

				bool WriteXmlPropToFile(String^ fullPath, String^ propPath);

				//! Write a property branch to the registry - can be used to save a "Preset"
				bool WriteXmlPropToRegistry(String^ regKeyName, String^ regValueName, String^ propPath, String^ regPath);

				//! Read a property branch from the registry - can be used to read a "Preset"
				bool ReadXmlPropFromRegistry(String^ regKeyName, String^ regValueName, String^ regPath);

				//! Read an XML file from MyDocument dir
				bool ReadXmlPropFromMyDocument(String^ subDir, String^ filename);

				//! Write property branch to an XML file in MyDocument dir
				bool WriteXmlPropToMyDocument(String^ subDir, String^ filename, String^ propPath);

				static property String^ UserMyDocumentDir
				{
					String^ get();
				}



				enum class LoadMode
				{
					Merge = KFbxIOSettings::eMERGE,
					ExclusiveMerge = KFbxIOSettings::eEXCLUSIVE_MERGE,
					Create = KFbxIOSettings::eCREATE
				};
				enum class QuaternionMode
				{
					AsQuaternion = KFbxIOSettings::eAS_QUATERNION,
					AsEuler= KFbxIOSettings::eAS_EULER,
					Resample= KFbxIOSettings::eRESAMPLE
				};
				enum class ObjectDerivation
				{
					ByLayer= KFbxIOSettings::eBY_LAYER, 
					ByEntity= KFbxIOSettings::eBY_ENTITY, 
					ByBlock= KFbxIOSettings::eBY_BLOCK
				}; 

				enum class SysUnits
				{
					User = KFbxIOSettings::kUNITS_USER ,
					Inches = KFbxIOSettings::kUNITS_INCHES, 
					Feet= KFbxIOSettings::kUNITS_FEET,
					Yards= KFbxIOSettings::kUNITS_YARDS,
					Miles= KFbxIOSettings::kUNITS_MILES,
					Millimeters= KFbxIOSettings::kUNITS_MILLIMETERS,
					Centimeters= KFbxIOSettings::kUNITS_CENTIMETERS,
					Meters= KFbxIOSettings::kUNITS_METERS,
					Kilometers= KFbxIOSettings::kUNITS_KILOMETERS
				};

				enum class SysFrameRate  
				{
					User = KFbxIOSettings::kFRAMERATE_USER,
					Hour= KFbxIOSettings::kFRAMERATE_HOURS,
					Minutes= KFbxIOSettings::kFRAMERATE_MINUTES,
					Seconds= KFbxIOSettings::kFRAMERATE_SECONDS,
					Milliseconds= KFbxIOSettings::kFRAMERATE_MILLISECONDS,
					Games_15= KFbxIOSettings::kFRAMERATE_GAMES_15,
					Film_24= KFbxIOSettings::kFRAMERATE_FILM_24,
					Pal_25= KFbxIOSettings::kFRAMERATE_PAL_25,
					Ntsc_30= KFbxIOSettings::kFRAMERATE_NTSC_30,
					Showscan_48= KFbxIOSettings::kFRAMERATE_SHOWSCAN_48,
					Palfield_50= KFbxIOSettings::kFRAMERATE_PALFIELD_50,
					Ntscfield_60= KFbxIOSettings::kFRAMERATE_NTSCFIELD_60
				};

				// Max
				enum class EnveloppeSystem
				{
					SkinModifier= KFbxIOSettings::eSKIN_MODIFIER,
					Physique= KFbxIOSettings::ePHYSIQUE,
					Bonespro= KFbxIOSettings::eBONESPRO,
					EnveloppeSystemCount= KFbxIOSettings::eENVELOPPE_SYSTEM_COUNT
				};

				// Max
				enum class GeometryType
				{
					Triangle = KFbxIOSettings::eTRIANGLE,
					SimplifiedPoly= KFbxIOSettings::eSIMPLIFIED_POLY,
					Poly= KFbxIOSettings::ePOLY,
					Nurb= KFbxIOSettings::eNURB,
					Patch= KFbxIOSettings::ePATCH,
					GeometryTypeCount= KFbxIOSettings::eGEOMETRY_TYPE_COUNT
				};

				REF_PROPERTY_GET_DECLARE(FbxSoInfo,ImpInfo);
				REF_PROPERTY_GET_DECLARE(FbxSoInfo,ExpInfo);				

				property FbxUILanguage UILanguage
				{
					FbxUILanguage get();
					void set(FbxUILanguage value);
				}				

				//FbxPropInfo^ GetPropInfo(FbxProperty^ prop);
				String^ GetLanguageLabel(FbxProperty^ prop);
				void SetLanguageLabel(FbxProperty^ prop, String^ label);
				FbxUILanguage GetMaxRuntimeLanguage(String^ regLocation);

				bool IsEnumExist(FbxProperty^ prop, String^ enumString);
				int  GetEnumIndex(FbxProperty^ prop, String^ enumString, bool noCase);

				CLONE_DECLARE();

			};


		}
	}
}